/* Copyright 2008 Shawn C. Dodd

This file is part of TagFC.  TagFC is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

TagFC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with TagFC.  If not, see <http://www.gnu.org/licenses/>. */

class WorkService {

	boolean transactional = true

	def sessionFactory					// injected
	def accountService					// injected

	def leaseNewWorkset(nickname) { leaseNewWorkset(nickname,null) }

	def leaseNewWorkset(nickname, previous) {
		// Lease available Pieces to create a new Workset
		// TODO  implement "previous" support (prefetch)
		def set = new Workset()
		set.nickname = Nickname.findByDisplayName(nickname)
		
		def next = Piece.createCriteria()
		def included = next.list {
			and {
				eq( "state", "unproc" )
				or {
					isNull( "leaseExpiry" )
					lt( "leaseExpiry", new Date() )
				}
			}
			maxResults(100)		// TODO  should be twice this
//			order( "dateCreated", "asc" )		// bad for DB performance
		}
		def future = new Date() + 1			// days
		included.each { 
			it.leaseExpiry = future
			set.addToIncluded(it)
		}

		def saved = set.save(flush:true)
		if( !saved ) {
			log.error "Oops! Couldn't create a new Workset:"
			set.errors.allErrors.each { log.error "Couldn't create workset: $it" }
		}
		return set;
	}

	def retireWorkset(set, changes) {
		// Apply the given changes and discard everything else
		def hibSession = sessionFactory.getCurrentSession()
		int delCount = 0
		int tagCount = 0
		HashSet ch = new HashSet(changes)
		HashSet inc = new HashSet(set.included)
		inc.each {
			def pid = it.id as String
			boolean wasTagged = Piece.get(pid)?.state == "tagged"
			if( ch.contains(pid) ) {
				// checked, so tag and change state
				if( wasTagged ) return
				tag( pid, "car", set.nickname.displayName )
				tagCount++
			} else {
				// unchecked, so delete
				if( wasTagged ) tagCount--
				rem( set, it )
				del( pid, set.nickname.displayName )
				delCount++
			}
		}
		
		// generate an invoice for the logged-in Farmer
		def period = accountService.currentPeriod()
		accountService.invoiceSummarized( set.nickname.displayName, period, delCount+tagCount, tagCount )

		def saved = set.save()
		if(!saved) set.error.allErrors.each { log.error "Couldn't save Workset: $it" }
		log.error "Discarded $delCount pieces by ($set.nickname.displayName)"
		hibSession.flush()
	}

	void tag( String pid, String tags, String nickname ) {
                def p = Piece.get(pid)
                p.simpleEntry.tags = tags
                p.state = "tagged"
                def saved = p.save()
                if(!saved) p.errors.allErrors.each { log.error "Problem tagging Piece ${pid}; $it" }
                else log.error "Successfully tagged Piece ${pid} by (${nickname})"
	}

	def rem( set, piece ) {
		set.removeFromIncluded(piece)
	}

	void del( String pid, String nickname ) {
		def p = Piece.get(pid)
		p.delete()
	}
/*
AccountService {
def invoiceSummarized( nickname, period, seen, completed ) {
*/
}
